#include <QMouseEvent>
#include <QPainter>
#include "core/disp/disp.h"
#include "disp/surfaceimpl.h"
#include "drawingsurface.h"
#include "global.h"

namespace ShUi
{

class DrawingSurfaceImpl : public Impl<DrawingSurface>
{
public:
    void init();
    void exit();
    Surface* _iSurface;
};

void DrawingSurfaceImpl::init()
{
    SH_Q(DrawingSurface);
    _iSurface = new Surface(q);
    q->setBgColor(VgBgColor);
    q->setAutoFillBackground(true);
    q->setFocusPolicy(Qt::WheelFocus);
}

void DrawingSurfaceImpl::exit()
{
    SH_SAFE_DELETE(_iSurface);
}

DrawingSurface::DrawingSurface(QWidget *parent) :
    QWidget(parent)
{
    SH_I(DrawingSurface);
    d->init();
}

DrawingSurface::~DrawingSurface()
{
    SH_E(DrawingSurface);
    d->exit();
}

void DrawingSurface::setBgColor(const QColor& color)
{
    QPalette palette;
    palette.setColor(backgroundRole(), color);
    setPalette(palette);
    //setPalette(QPalette(color));
}

void DrawingSurface::setPenColor(const QColor& color)
{
    SH_D(DrawingSurface);
    SsWireAt at = *d->_iSurface->attribute();
    at.color.r = color.red();
    at.color.g = color.green();
    at.color.b = color.blue();
    at.color.a = color.alpha();
    d->_iSurface->setAttribute(&at);
}

void DrawingSurface::setPenWidth(int width)
{
    SH_D(DrawingSurface);
    SsWireAt at = *d->_iSurface->attribute();
    at.width = width;
    d->_iSurface->setAttribute(&at);
}

void DrawingSurface::keyPressEvent(QKeyEvent* evt)
{
    SH_D(DrawingSurface);
    SsUiEvent sEvent;
    sEvent.type = S_KEY_DN;
    sEvent.wkey.key = evt->nativeVirtualKey();
    sEvent.wkey.cnt = evt->count();
    sEvent.wkey.state = S_MASK_NULL;
    d->_iSurface->event(&sEvent);
}

void DrawingSurface::keyReleaseEvent(QKeyEvent* evt)
{
    SH_D(DrawingSurface);
    SsUiEvent sEvent;
    sEvent.type = S_KEY_UP;
    sEvent.wkey.key = evt->nativeVirtualKey();
    sEvent.wkey.cnt = evt->count();
    sEvent.wkey.state = S_MASK_NULL;
    d->_iSurface->event(&sEvent);

}

void DrawingSurface::mouseDoubleClickEvent(QMouseEvent* evt)
{
    SH_D(DrawingSurface);
    SsUiEvent sEvent;
    sEvent.type = S_BUTTON_DCLICK;
    sEvent.wbutton.button = S_BTN1_DC;
    sEvent.wbutton.x = evt->x();
    sEvent.wbutton.y = evt->y();
    sEvent.wbutton.state = S_MASK_NULL;
    if (evt->buttons() & Qt::LeftButton)
        sEvent.wbutton.state |= S_MASK_LBUTTON;
    if (evt->buttons() & Qt::ShiftModifier)
        sEvent.wbutton.state |= S_MASK_SHIFT;
    if (evt->buttons() & Qt::ControlModifier)
        sEvent.wbutton.state |= S_MASK_CONTROL;
    if (evt->buttons() & Qt::AltModifier)
        sEvent.wbutton.state |= S_MASK_ALT;
    d->_iSurface->event(&sEvent);
}

void DrawingSurface::mousePressEvent(QMouseEvent* evt)
{
    SH_D(DrawingSurface);
    SsUiEvent sEvent;
    if (evt->button() & Qt::LeftButton)
        sEvent.wbutton.button = S_BTN1_DN;
    else if (evt->button() & Qt::MiddleButton)
        sEvent.wbutton.button = S_BTN2_DN;
    else if (evt->button() & Qt::RightButton)
        sEvent.wbutton.button = S_BTN3_DN;
    else
        return;
    sEvent.type = S_BUTTON_DOWN;
    sEvent.wbutton.x = evt->x();
    sEvent.wbutton.y = evt->y();
    sEvent.wbutton.state = S_MASK_NULL;
    if (evt->buttons() & Qt::LeftButton)
        sEvent.wbutton.state |= S_MASK_LBUTTON;
    if (evt->buttons() & Qt::ShiftModifier)
        sEvent.wbutton.state |= S_MASK_SHIFT;
    if (evt->buttons() & Qt::ControlModifier)
        sEvent.wbutton.state |= S_MASK_CONTROL;
    if (evt->buttons() & Qt::AltModifier)
        sEvent.wbutton.state |= S_MASK_ALT;
    d->_iSurface->event(&sEvent);
}

void DrawingSurface::mouseMoveEvent(QMouseEvent* evt)
{
    SH_D(DrawingSurface);
    SsUiEvent sEvent;
    sEvent.type = S_MOUSE_MOVE;
    sEvent.wmotion.x = evt->x();
    sEvent.wmotion.y = evt->y();
    sEvent.wmotion.state = S_MASK_NULL;
    if (evt->buttons() & Qt::LeftButton)
        sEvent.wmotion.state |= S_MASK_LBUTTON;
    if (evt->buttons() & Qt::ShiftModifier)
        sEvent.wmotion.state |= S_MASK_SHIFT;
    if (evt->buttons() & Qt::ControlModifier)
        sEvent.wmotion.state |= S_MASK_CONTROL;
    if (evt->buttons() & Qt::AltModifier)
        sEvent.wmotion.state |= S_MASK_ALT;
    d->_iSurface->event(&sEvent);
}

void DrawingSurface::mouseReleaseEvent(QMouseEvent* evt)
{
    SH_D(DrawingSurface);
    SsUiEvent sEvent;
    if (evt->button() & Qt::LeftButton)
        sEvent.wbutton.button = S_BTN1_UP;
    else if (evt->button() & Qt::MiddleButton)
        sEvent.wbutton.button = S_BTN2_UP;
    else if (evt->button() & Qt::RightButton)
        sEvent.wbutton.button = S_BTN3_UP;
    else
        return;
    sEvent.type = S_BUTTON_UP;
    sEvent.wbutton.x = evt->x();
    sEvent.wbutton.y = evt->y();
    sEvent.wbutton.state = S_MASK_NULL;
    if (evt->buttons() & Qt::LeftButton)
        sEvent.wbutton.state |= S_MASK_LBUTTON;
    if (evt->buttons() & Qt::ShiftModifier)
        sEvent.wbutton.state |= S_MASK_SHIFT;
    if (evt->buttons() & Qt::ControlModifier)
        sEvent.wbutton.state |= S_MASK_CONTROL;
    if (evt->buttons() & Qt::AltModifier)
        sEvent.wbutton.state |= S_MASK_ALT;
    d->_iSurface->event(&sEvent);
}

void DrawingSurface::enterEvent(QEvent*)
{
    SH_D(DrawingSurface);
    SsUiEvent sEvent;
    sEvent.type = S_ENTER_NOTIFY;
    d->_iSurface->event(&sEvent);
}

void DrawingSurface::leaveEvent(QEvent*)
{
    SH_D(DrawingSurface);
    SsUiEvent sEvent;
    sEvent.type = S_LEAVE_NOTIFY;
    d->_iSurface->event(&sEvent);
}

void DrawingSurface::wheelEvent(QWheelEvent* evt)
{
    SH_D(DrawingSurface);
    SsUiEvent sEvent;
    sEvent.type = S_MOUSE_WHEEL;
    sEvent.wwheel.x = evt->x();
    sEvent.wwheel.y = evt->y();
    sEvent.wwheel.delta = evt->delta();
    sEvent.wwheel.state = S_MASK_NULL;
    if (evt->buttons() & Qt::LeftButton)
        sEvent.wwheel.state |= S_MASK_LBUTTON;
    if (evt->buttons() & Qt::ShiftModifier)
        sEvent.wwheel.state |= S_MASK_SHIFT;
    if (evt->buttons() & Qt::ControlModifier)
        sEvent.wwheel.state |= S_MASK_CONTROL;
    if (evt->buttons() & Qt::AltModifier)
        sEvent.wwheel.state |= S_MASK_ALT;
    d->_iSurface->event(&sEvent);
}

void DrawingSurface::paintEvent(QPaintEvent* evt)
{
    SH_D(DrawingSurface);
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    QPixmap* pixmap = d->_iSurface->buffer();
    QRegion region = evt->region().intersected(pixmap->rect());
    QVector<QRect> rects = region.rects();
    int cnt = rects.size();
    for (int i = 0; i < cnt; ++i)
    {
        painter.drawPixmap(rects[i], *pixmap, rects[i]);
    }
}

void DrawingSurface::resizeEvent(QResizeEvent* evt)
{
    SH_D(DrawingSurface);
    d->_iSurface->resize(evt->size().width(), evt->size().height());
}

} // namespace ShUi
